package org.libarae.communication;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.libarae.communication.common.Type;
import org.libarae.communication.response.AccountInfoResponse;
import org.libarae.communication.response.AccountUpdateResponse;
import org.libarae.communication.response.AdminActionResponse;
import org.libarae.communication.response.AdminPanelResponse;
import org.libarae.communication.response.BookInfoResponse;
import org.libarae.communication.response.BookSearchResponse;
import org.libarae.communication.response.ChangeMessageStatusResponse;
import org.libarae.communication.response.CreateBookResponse;
import org.libarae.communication.response.EditBookResponse;
import org.libarae.communication.response.FeaturedTabResponse;
import org.libarae.communication.response.GenericResponse;
import org.libarae.communication.response.GetThreadMessageResponse;
import org.libarae.communication.response.HeartBeatResponse;
import org.libarae.communication.response.IsbnLookUpResponse;
import org.libarae.communication.response.LoginResponse;
import org.libarae.communication.response.LogoutResponse;
import org.libarae.communication.response.MailboxMessagesResponse;
import org.libarae.communication.response.ModeratorActionResponse;
import org.libarae.communication.response.ModeratorPanelResponse;
import org.libarae.communication.response.NewUserResponse;
import org.libarae.communication.response.PictureResponse;
import org.libarae.communication.response.ProfileTabResponse;
import org.libarae.communication.response.Response;
import org.libarae.communication.response.SendMessageResponse;
import org.libarae.communication.response.ServerInfoResponse;
import org.libarae.communication.response.ServerPingResponse;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class ResponseXmlHandler {

	/*
	 *  Parses a message from the string formated in the proper XML
	 *  
	 *  Takes the String that is the the xml
	 *  Returns the proper Request object with all of the information filled in	 * 
	 */
	public static Response parseXML(String message) throws SAXException, IOException, ParserConfigurationException, XmlParseException{
		//Set up the XML decoder	
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(new ByteArrayInputStream(message.getBytes()));
		doc.getDocumentElement().normalize();
		
		//get the type of the xml object
		int type;
		try{
			type = Integer.parseInt(doc.getDocumentElement().getAttribute("typeID"));
		}
		catch(NumberFormatException e){
			throw new XmlParseException("Could not parse numeric type from "+doc.getDocumentElement().getNodeName(),e);
		}
		
		//switch on the type to make the proper object
		Response obj;
		switch(type){
			case Type.BOOK_INFO:
				obj = new BookInfoResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.BOOK_SEARCH:
				obj = new BookSearchResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.CREATE_BOOK:
				obj = new CreateBookResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.FEATRUED_TAB:
				obj = new FeaturedTabResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.HEART_BEAT:
				obj = new HeartBeatResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.ISBN_LOOKUP:
				obj = new IsbnLookUpResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.LOGIN:
				obj = new LoginResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.MAILBOX_MESSAGES:
				obj = new MailboxMessagesResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.NEW_USER:
				obj = new NewUserResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.PROFILE_TAB:
				obj = new ProfileTabResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.SEND_MESSAGE:
				obj = new SendMessageResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.GENERIC:
				obj = new GenericResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.LOGOUT:
				obj = new LogoutResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.SERVER_PING:
				obj = new ServerPingResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.ACCOUNT_INFO:
				obj = new AccountInfoResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.ACCOUNT_UPDATE:
				obj = new AccountUpdateResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.MODERATOR_PANEL:
				obj = new ModeratorPanelResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.MODERATOR_ACTION:
				obj = new ModeratorActionResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.ADMIN_PANEL:
				obj = new AdminPanelResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.ADMIN_ACTION:
				obj = new AdminActionResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.SERVER_INFO:
				obj = new ServerInfoResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.CHANGE_MESSAGE_STATUS:
				obj = new ChangeMessageStatusResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.PICTURE:
				obj = new PictureResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.GET_THREAD_MESSAGES:
				obj = new GetThreadMessageResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			case Type.EDIT_BOOK:
				obj = new EditBookResponse(Response.STATUS_FAILED_GENERIC);
				obj.decodeXML(doc);
				return obj;
			default:
				throw new XmlParseException("Message Object Type ID not Reconginzed.");
		}			
	}
	
	/*
	 *  Creates the XML dumped to a String from the request object given.
	 *  
	 *  returns the String of xml
	 *   
	 */
	public static String createXML(Response object) throws XmlParseException{		
		return object.createXML();
	}	
}
